home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’96 / MenuHack / MenuHackSource.sit / MHPlug.cp < prev    next >
Text File  |  1996-06-21  |  18KB  |  617 lines

  1. #include "ArrangeCallbacks.h"
  2. #include "PluginLibrary.h"
  3.  
  4. #include <Dialogs.h>
  5. #include <StandardFile.h>
  6. #include <string.h>
  7. #include <Folders.h>
  8. #include <TextUtils.h>
  9. #include <Resources.h>
  10. #include <AppleEvents.h>
  11. #include <PLStringFuncs.h>        /* some special string handling stuff */
  12.  
  13. #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
  14.     #include "A4Stuff.h"
  15. #endif
  16.  
  17. #define ModuleRsrcID -0x8000
  18. #define SecondsInADay 86400
  19.  
  20. #define OurModuleID  0x70000048  // Unique module ID; replace with a value
  21.                                            // obtained from Common Knowledge.
  22. #define baseCmdCode  OurModuleID
  23.  
  24. #define aboutCmdCode (baseCmdCode + 0)
  25.  
  26. #define pluginName    "MHPlug" // controls our name in the About menu
  27.  
  28. #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
  29.     #define SetupA4            long    lOldA4 = SetCurrentA4 ();
  30.     #define TearDownA4         SetA4 (lOldA4);
  31.     #define UnloadSegs        UnloadSegsFunc ();
  32.  
  33.     static void UnloadSegsFunc ();
  34. #else
  35.     #define SetupA4
  36.     #define TearDownA4
  37.     #define UnloadSegs
  38. #endif    //__MWERKS__
  39.  
  40. typedef struct {
  41.         arDocumentPtr    whichDoc;
  42.         const ArrangeCallbackTbl* calls;
  43.     } myprefs;
  44.  
  45. typedef struct {
  46.         arNoteID    BookMarksTopic;
  47.         arNoteID    ClippingTopic;
  48.         arNoteID    InternetFolder;
  49.         arNoteID DataFolder;
  50.         arFieldID         lParentSubnoteFieldID;
  51.         arFieldID        lTopicContentsFieldID;
  52.         arFieldID        lURLFieldID;
  53.         arFieldID        lCommentID;
  54.         arFieldID        lTitleField;
  55.         arNoteID            lURLNoteID;
  56.     
  57.     } sIDList;
  58.  
  59. static Boolean GetMyIDs(myprefs* theprefs, sIDList *theIDs)
  60. {
  61.     char    Internetname[16] = "Internet";
  62.     char    CommentName[16] = "Comment";
  63.     char    URLName[16] = "URL";
  64.     char    ClippingTopicName[32] = "Clippings";
  65.     char    TitleName[32] = "Title";
  66.     char    BookTopicName[16] = "BookMarks";
  67.         
  68.     theIDs->DataFolder = theprefs->calls->sysObj->GetBuiltInObject (boOrganizerFolder);
  69.     if (!theIDs->DataFolder)
  70.     {
  71.         return false;
  72.     }
  73.     theIDs->lParentSubnoteFieldID = theprefs->calls->sysObj->GetBuiltInObject (boSubnotesField);
  74.     if (!theIDs->lParentSubnoteFieldID)
  75.     {
  76.         return false;
  77.     }
  78.     
  79.     theIDs->lTopicContentsFieldID = theprefs->calls->sysObj->GetBuiltInObject (boTopicContentsField);
  80.     if (!theIDs->lTopicContentsFieldID)
  81.     {
  82.         return false;
  83.     }
  84.     
  85.     theIDs->lURLNoteID = theprefs->calls->sysObj->LookupObjectName ( arNoteType,(char*) (&URLName), true);
  86.     if (!theIDs->lURLNoteID)
  87.     {
  88.         theIDs->lURLNoteID = theprefs->calls->sysObj->CreateNoteType((char*)(&URLName), true);
  89.         if (!theIDs->lURLNoteID)
  90.         {
  91.             return false;
  92.         }
  93.     }
  94.     
  95.     theIDs->lTitleField = theprefs->calls->sysObj->LookupObjectName ( arField,(char*) (&TitleName), true);
  96.     if (!theIDs->lTitleField)
  97.     {
  98.         theIDs->lTitleField = theprefs->calls->sysObj->CreateField((char*)(&TitleName), arFTText, true);
  99.         if (!theIDs->lTitleField)
  100.         {
  101.             return false;
  102.         }
  103.     }
  104.     if (!theprefs->calls->notes->NoteHasField(theIDs->lURLNoteID, theIDs->lTitleField, false))
  105.     {
  106.         theprefs->calls->notes->AddField(theIDs->lURLNoteID, theIDs->lTitleField, nil);
  107.     }
  108.     
  109.     theIDs->lURLFieldID = theprefs->calls->sysObj->LookupObjectName ( arField,(char*) (&URLName), true);
  110.     if (!theIDs->lURLFieldID)
  111.     {
  112.         theIDs->lURLFieldID = theprefs->calls->sysObj->CreateField((char*)(&URLName), arFTText, true);
  113.         if (!theIDs->lURLFieldID)
  114.         {
  115.             return false;
  116.         }
  117.     }
  118.     theIDs->lCommentID = theprefs->calls->sysObj->LookupObjectName ( arField,(char*) (&CommentName), true);
  119.     if (!theIDs->lCommentID)
  120.     {
  121.         theIDs->lCommentID = theprefs->calls->sysObj->CreateField((char*)(&CommentName), arFTText, true);
  122.         if (!theIDs->lCommentID)
  123.         {
  124.             return false;
  125.         }
  126.     }
  127.     
  128.     theIDs->InternetFolder = theprefs->calls->sysObj->LookupObjectName ( arFolder,(char*) (&Internetname), false);
  129.     if (!theIDs->InternetFolder)
  130.     {
  131.         theIDs->InternetFolder = theprefs->calls->sysObj->CreateFolder( (char*)(&Internetname), nil);
  132.         if (!theIDs->InternetFolder)
  133.         {
  134.             return false;
  135.         }
  136.     }
  137.     
  138.     theIDs->ClippingTopic = theprefs->calls->sysObj->LookupObjectName ( arTopic,(char*) (&ClippingTopicName), false);
  139.     if (!theIDs->ClippingTopic)
  140.     {
  141.         theIDs->ClippingTopic = theprefs->calls->sysObj->CreateTopic( (char*)(&ClippingTopicName), theIDs->DataFolder, nil, false);
  142.         if (!theIDs->ClippingTopic)
  143.         {
  144.             return false;
  145.         }
  146.     }
  147.     theIDs->BookMarksTopic = theprefs->calls->sysObj->LookupObjectName ( arTopic,(char*) (&BookTopicName), false);
  148.     if (!theIDs->BookMarksTopic)
  149.     {
  150.         theIDs->BookMarksTopic = theprefs->calls->sysObj->CreateTopic( (char*)(&BookTopicName), theIDs->InternetFolder, nil, false);
  151.         if (!theIDs->BookMarksTopic)
  152.         {
  153.             return false;
  154.         }
  155.     }
  156.     return true;    
  157. }
  158.  
  159. void AppendNoteToField (const ArrangeCallbackTbl* calls, arNoteID lURLNoteID, arNoteID lParentNoteID, arFieldID lParentSubnoteFieldID)
  160. {
  161.     Integer    lInsertionIndex;
  162.  
  163.     lInsertionIndex = calls->data->GetFieldListLen (lParentNoteID, lParentSubnoteFieldID);
  164.     calls->data->AddListFieldEntry (lParentNoteID, lParentSubnoteFieldID, lInsertionIndex, lURLNoteID, nullSFF);
  165.     calls->doc->SetChangedFlag ();
  166. }
  167.  
  168. // This apple event gets the nth URL note in bookmarks
  169.  
  170. static pascal OSErr aeGetAURL(const AppleEvent *theAppleEvent, 
  171.     AppleEvent *reply, myprefs* theprefs)
  172. {
  173.     OSErr        anErr;
  174.     OSType        typeCode;
  175.     long        thesize;
  176.     long        whichURL;
  177.     arDocumentPtr    tempDoc;
  178.     long        lTopicCount;
  179.     arNoteID    lCurNote;
  180.     sIDList    theIDs;
  181.     Str255    tempstr;
  182.     unsigned long    templong;
  183.     
  184.     anErr = AEGetParamPtr(theAppleEvent, '----', typeLongInteger, &typeCode,
  185.         &whichURL, sizeof(whichURL), &thesize);
  186.     if (anErr!=noErr)
  187.     {
  188.         return anErr;
  189.     }
  190.     
  191.     tempDoc = theprefs->calls->doc->GetCurrentDoc ();
  192.     theprefs->calls->doc->SetCurrentDoc(theprefs->whichDoc);
  193.     if (!GetMyIDs(theprefs, &theIDs))
  194.     {
  195.         //DebugStr("\pWhoops");
  196.         return -1;
  197.     }
  198.     lTopicCount = theprefs->calls->data->GetFieldListLen (theIDs.BookMarksTopic, theIDs.lTopicContentsFieldID);
  199.     anErr = AEPutParamPtr( reply, 'tCnt', typeLongInteger, (const void*)&lTopicCount, sizeof(lTopicCount) );
  200.     
  201.     if ((whichURL>0) && (whichURL<=lTopicCount))
  202.     {
  203.         lCurNote = theprefs->calls->data->GetFieldListEntry (theIDs.BookMarksTopic, theIDs.lTopicContentsFieldID,whichURL-1);
  204.         
  205.         thesize = theprefs->calls->data->GetFieldText(lCurNote, theIDs.lURLFieldID, 255,  (char*)&tempstr[1]);
  206.         tempstr[0] = thesize;
  207.         anErr = AEPutParamPtr( reply, 'URL ', typeChar, (const void*)&tempstr[1], tempstr[0] );
  208.         if (anErr!=noErr)
  209.         {
  210.             return anErr;
  211.         }
  212.         
  213.         thesize = theprefs->calls->data->GetFieldText(lCurNote, theIDs.lCommentID, 255,  (char*)&tempstr[1]);
  214.         tempstr[0] = thesize;
  215.         anErr = AEPutParamPtr( reply, 'Comm', typeChar, (const void*)&tempstr[1], tempstr[0] );
  216.         if (anErr!=noErr)
  217.         {
  218.             return anErr;
  219.         }
  220.         thesize = theprefs->calls->data->GetFieldText(lCurNote, theIDs.lTitleField, 255,  (char*)&tempstr[1]);
  221.         tempstr[0] = thesize;
  222.         anErr = AEPutParamPtr( reply, 'Titl', typeChar, (const void*)&tempstr[1], tempstr[0] );
  223.         if (anErr!=noErr)
  224.         {
  225.             return anErr;
  226.         }
  227.         
  228.     }
  229.     theprefs->calls->doc->SetCurrentDoc(tempDoc);
  230.     
  231.     return noErr;
  232. }
  233.  
  234. static void InstallMe(myprefs* theprefs)
  235. {
  236.     OSErr    aevtErr;
  237.     
  238.     aevtErr = AEInstallEventHandler( 'MHck', 'GtUr',(AEEventHandlerUPP)aeGetAURL, (long)theprefs, false ) ;
  239. }
  240.  
  241. class Plugin
  242.     {
  243. public:
  244.     Plugin(const ArrangeCallbackTbl* theCalls);
  245.     ~Plugin();
  246.     
  247.     arHookResult ClickNotify( arClickLocation loc, Point where, Short modifiers,
  248.                                       Short clickCount, arNoteID note, arFieldID field,
  249.                                       arPathID path );
  250.     arHookResult KeyNotify  ( Short theChar, Short key, Short modifiers );
  251.     arHookResult MenuNotify ( Integer commandCode, Integer commandParam,
  252.                                       Short modifiers );
  253.     void AboutToMenu();
  254.     arHookResult FieldNotify( arNoteID note, arFieldID field, arFieldAction action,
  255.                                       const char* choiceText );
  256.     void         TopicNotify( arTopicID newTopic, arWindowID newWindow,
  257.                                       arTopicAction action );
  258.     void             TickNotify (  );
  259.     arHookResult FileNotify ( arFileAction action );
  260.     arHookResult QuitNotify (  );
  261.     void         ATMNotify  (  );
  262.     
  263. private:
  264.     void        WriteANote ( arNoteID note);
  265.     void        ReadANote ( );
  266.     const ArrangeCallbackTbl* calls; // callback table
  267.     myprefs    theprefs;
  268.     }; // Plugin
  269.  
  270.  
  271. /*************************************************************************/
  272. /**************************** Main entry point ***************************/
  273. /*************************************************************************/
  274.  
  275. /* Root entry point for the module - must be the first function in the
  276.  * file, so that the linker will place it first in the code segment.
  277.  * This is the routine which Arrange calls at application startup time
  278.  * (and again at quit time).
  279.  * 
  280.  * Most plug-ins will not need to modify this routine or the Hook functions
  281.  * immediately following.  All customization can be done in the "Plugin"
  282.  * section (below).
  283.  */
  284. extern "C" Integer main( ModuleParamBlock *pb, pModuleRootAction action,
  285.                                             Integer /*p1*/ )
  286.     {
  287.     SetupA4;
  288.  
  289.     Integer    lResult = 0;
  290.  
  291.     /* Extract the callback table from our parameter block, and coerce it
  292.      * to the extended Arrange table.
  293.      */
  294.     ArrangeCallbackTbl* calls = (ArrangeCallbackTbl*)(pb->calls);
  295.     
  296.     Assert (sizeof (Byte) == 1);
  297.     Assert (sizeof (Short) == 2);
  298.     Assert (sizeof (Integer) == 4);
  299.     Assert (sizeof (Float) == 8);
  300.  
  301.     switch (action)
  302.         {
  303.         case mrLoad:
  304.             {
  305.             // Allocate memory and create a new Plugin object.
  306.             void* storage = calls->mem->AllocMem( sizeof(Plugin),
  307.                                                               amFreeStore | amErrIfNoMem );
  308.             pb->moduleRefcon = uInteger(new(storage) Plugin(calls));
  309.             lResult = 1;
  310.             }
  311.             break;
  312.         
  313.         case mrUnload:
  314.             {
  315.             /* Dispose of the Plugin object and release the memory
  316.              * it occupies.
  317.              */
  318.             delete (Plugin*)(pb->moduleRefcon);
  319.             calls->mem->DeallocMem((void*)(pb->moduleRefcon), amFreeStore);
  320.             lResult = 0;
  321.             }
  322.             break;
  323.         
  324.         case mrFindEntry:
  325.         default:
  326.             {
  327.             /* This module contains no extended entry points, so we always
  328.              * return 0 for the mrFindEntry message.  Most plug-ins will not
  329.              * use extended entry points.
  330.              */
  331.             lResult = 0;
  332.             }
  333.             break;
  334.         
  335.         } // switch (action)
  336.     
  337.     TearDownA4;
  338.     return lResult;
  339.     } // main
  340.  
  341. #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
  342. #pragma segment PluginLib
  343. static void PluginLibSeg (void)
  344. {
  345. }
  346.  
  347. #pragma segment Main
  348. static void UnloadSegsFunc ()
  349. {
  350.     // Put segment unloading code here.
  351.     // Do NOT use UnloadSeg!
  352.     //UnloadA4Seg (PluginLibSeg);
  353. }
  354. #endif    //__MWERKS__ && PLUGIN_GLOBALS
  355.  
  356. /* These hook functions simply pass control to the appropriate function
  357.  * in the Plugin object.
  358.  */
  359. static arHookResult OurClickHook( ModuleParamBlock* pb, arClickLocation loc,
  360.                                              Point where, pShort modifiers, pShort clickCount,
  361.                                              arNoteID note, arFieldID field,
  362.                                              arPathID path ENDP )
  363.     {
  364.     SetupA4;
  365.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->ClickNotify( loc, where, modifiers,
  366.                                                                         clickCount, note, field,
  367.                                                                         path );
  368.     TearDownA4;
  369.     return eResult;
  370.     }
  371.  
  372.  
  373. static arHookResult OurKeyHook( ModuleParamBlock* pb, pShort theChar, pShort key,
  374.                                           pShort modifiers ENDP )
  375.     {
  376.     SetupA4;
  377.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->KeyNotify(theChar, key, modifiers);
  378.     TearDownA4;
  379.     return eResult;
  380.     }
  381.  
  382.  
  383. static arHookResult OurMenuHook( ModuleParamBlock* pb, Integer commandCode,
  384.                                             Integer commandParam, pShort modifiers ENDP )
  385.     {
  386.     SetupA4;
  387.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->MenuNotify( commandCode, commandParam,
  388.                                                                      modifiers );
  389.     TearDownA4;
  390.     return eResult;
  391.     }
  392.  
  393.  
  394. void OurATMHook(ModuleParamBlock* pb)
  395.     {
  396.     ((Plugin*)(pb->moduleRefcon))->AboutToMenu();
  397.     } // OurATMHook
  398.  
  399.  
  400. static arHookResult OurFieldHook( ModuleParamBlock* pb, arNoteID note,
  401.                                              arFieldID field, arFieldAction action,
  402.                                              const char* choiceText ENDP )
  403.     {
  404.     SetupA4;
  405.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->FieldNotify( note, field, action,
  406.                                                                         choiceText );
  407.     TearDownA4;
  408.     return eResult;
  409.     }
  410.  
  411.  
  412. static void OurTopicHook( ModuleParamBlock* pb, arTopicID newTopic,
  413.                                   arWindowID newWindow, arTopicAction action ENDP )
  414.     {
  415.     SetupA4;
  416.     ((Plugin*)(pb->moduleRefcon))->TopicNotify(newTopic, newWindow, action);
  417.     TearDownA4;
  418.     }
  419.  
  420.  
  421. static void OurTickHook(ModuleParamBlock* pb ENDP)
  422.     {
  423.     SetupA4;
  424.     ((Plugin*)(pb->moduleRefcon))->TickNotify();
  425.     TearDownA4;
  426.     }
  427.  
  428.  
  429. static arHookResult OurFileHook(ModuleParamBlock* pb, arFileAction action ENDP)
  430.     {
  431.     SetupA4;
  432.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->FileNotify(action);
  433.     TearDownA4;
  434.     return eResult;
  435.     }
  436.  
  437.  
  438. static arHookResult OurQuitHook(ModuleParamBlock* pb ENDP)
  439.     {
  440.     SetupA4;
  441.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->QuitNotify();
  442.     TearDownA4;
  443.     return eResult;
  444.     }
  445.  
  446.  
  447. /*************************************************************************/
  448. /********************************* Plugin ********************************/
  449. /*************************************************************************/
  450.  
  451. /* Construct a Plugin object.  This is called once, from the OurModuleRoot
  452.  * function, when the module is initialized (i.e. at application startup time).
  453.  */
  454. Plugin::Plugin(const ArrangeCallbackTbl* theCalls)
  455.     {
  456.     short    thelength;
  457.     arDocumentPtr    theCurDoc;
  458.     arDocumentPtr    thePrefDoc;
  459.     Str255            ourname;
  460.     Handle            temph;
  461.     
  462.     // Record the callback table for future use.
  463.     calls = theCalls;
  464.     
  465.     /* These commands, if un-commented-out, register this plugin to be called
  466.      * by Arrange when various events occur.  For example, if you un-comment-out
  467.      * the call to SetClickHook, then Plugin::ClickNotify will be called
  468.      * whenever the user clicks in any of the locations described in the
  469.      * arClickLocation enum.
  470.      */
  471.     // calls->ui->SetClickHook(OurClickHook, 0, true);
  472.     // calls->ui->SetKeyHook  (OurKeyHook,   0, true, charFilter, keyFilter, modFilter);
  473.     // calls->ui->SetMenuHook (OurMenuHook,  0, true, whichCommand);
  474.     // calls->ui->SetFieldHook(OurFieldHook, 0, true, whichField);
  475.     calls->ui->SetTopicHook(OurTopicHook, 0, true);
  476.     // calls->ui->SetFileHook (OurFileHook,  0, true);
  477.     // calls->ui->SetQuitHook (OurQuitHook,  0, true);
  478.     calls->ui->SetTickHook (OurTickHook,  0, true);
  479.     calls->ui->SetATMHook  (OurATMHook,   0, true);
  480.     
  481.     // Add an item to the About Plugins menu for this plugin.
  482.     temph = GetResource('STR ', ModuleRsrcID+1); // "About MenuHack"
  483.     BlockMove ((Ptr)*temph, (Ptr)(&ourname), 50);
  484.     ourname[ourname[0]+1] = 0; //Make good for C String
  485.     
  486.     calls->ui->AddMenuItem(mPluginAbout,  (char *)(&ourname[1]), 0, aboutCmdCode, 1);
  487.     
  488.     calls->ui->SetMenuHook(OurMenuHook, 1, true, aboutCmdCode);
  489.     
  490.     InstallMe(&theprefs);
  491.     
  492.     } // Plugin constructor
  493.  
  494.  
  495. /* Dispose of a Plugin object.  This is called when Arrange terminates.  You
  496.  * should free up any data structures which you allocation in the Plugin
  497.  * constructor (above).
  498.  */
  499. Plugin::~Plugin()
  500.     {
  501.     } // ~Plugin
  502.  
  503.  
  504. /* This function is called whenever the user clicks in an "interesting place"
  505.  * in a document window.  It should return true if we handle the click, false
  506.  * (the normal case) when the click should be passed along to other plug-ins
  507.  * or to Arrange's normal event processing.  See the documentation for
  508.  * SetClickHook for more details.
  509.  */
  510. arHookResult Plugin::ClickNotify( arClickLocation loc, Point where,
  511.                                              Short modifiers, Short clickCount,
  512.                                              arNoteID note, arFieldID field,
  513.                                              arPathID path )
  514.     {
  515.     return false; // Let Arrange handle the event
  516.     } // ClickNotify
  517.  
  518.  
  519. /* This function is called whenever the user types a key which matches the
  520.  * filters we pass to SetKeyHook in Plugin's constructor.  It should return
  521.  * true if we handle the event, false (the normal case) when the event
  522.  * should be passed along to other plug-ins or to Arrange's normal event
  523.  * processing.  See the documentation for SetKeyHook for more details.
  524.  */
  525. arHookResult Plugin::KeyNotify(Short theChar, Short key, Short modifiers)
  526.     {
  527.     return false; // Let Arrange handle the event
  528.     } // KeyNotify
  529. /* This function is called whenever the user clicks in the menu bar or types
  530.  * a command key, just before processing the event.  It does any fixing up
  531.  * of menus which might be necessary based on the current state of affairs.
  532.  */
  533. void Plugin::AboutToMenu()
  534. {
  535. }
  536.  
  537.  
  538.  
  539. arHookResult Plugin::MenuNotify( Integer commandCode, Integer commandParam,
  540.                                             Short modifiers )
  541.     {
  542.     /* If this is our About menu item, display our about-box dialog and return
  543.      * true to indicate we handled the command.
  544.      */
  545.     if (commandCode == aboutCmdCode)
  546.         {
  547.         Alert(ModuleRsrcID, nil);
  548.         return true;
  549.         }
  550.     return false; // Let Arrange handle the event
  551.     
  552.     } // MenuNotify
  553.  
  554.  
  555. /* If we register to recieve events for a field by calling SetFieldHook, this
  556.  * function will be called for any events in that field.  It should return
  557.  * false in almost all cases.  See the documentation for SetFieldHook for
  558.  * more details.
  559.  */
  560. arHookResult Plugin::FieldNotify( arNoteID note, arFieldID field,
  561.                                              arFieldAction action, const char* choiceText )
  562.     {
  563.     return false;
  564.     } // FieldNotify
  565.  
  566.  
  567. /* This function is called whenever the user switches windows or changes
  568.  * the current folder/topic/view in the front window.  See the documentation
  569.  * for SetTopicHook for more details.
  570.  */
  571. void Plugin::TopicNotify( arTopicID newTopic, arWindowID newWindow,
  572.                                   arTopicAction action )
  573.     {
  574.     theprefs.calls = calls;
  575.     theprefs.whichDoc = calls->doc->GetCurrentDoc ();
  576.     } // TopicNotify
  577.  
  578.  
  579. /* This function is called periodically, whenever Arrange recieves a null
  580.  * event from the Event Manager.
  581.  */
  582. void Plugin::TickNotify()
  583.     {
  584.         OSErr    err;
  585.         
  586.     } // TickNotify
  587.  
  588.  
  589. /* This function is called whenever various file-level events occur.  It
  590.  * should return true in almost all cases.  See the documentation for
  591.  * SetFileHook for more details.
  592.  */
  593. arHookResult Plugin::FileNotify(arFileAction action)
  594.     {
  595.     return true;
  596.     } // FileNotify
  597.  
  598.  
  599. /* This function is called if the user voluntarily quits Arrange.  It should
  600.  * return true to allow the user to quit, false to prevent it.  See the
  601.  * documentation for SetQuitHook for more details.
  602.  */
  603. arHookResult Plugin::QuitNotify()
  604.     {
  605.     return true;
  606.     } // QuitNotify
  607.  
  608.  
  609. /* This function is called whenever the user clicks in the menu bar or types
  610.  * a command key, just before processing the event.  It should do any fixing
  611.  * up of menus which might be necessary based on the current state of affairs.
  612.  * See the documentation for SetATMHook for more details.
  613.  */
  614. void Plugin::ATMNotify()
  615.     {
  616.     } // ATMNotify
  617.